/**
 * ============后端应用主文件开始===========
 * 这是整个后端应用的核心配置文件，负责：
 * 1. 初始化 Express 服务器
 * 2. 配置中间件和安全设置
 * 3. 注册所有 API 路由
 * 4. 设置错误处理机制
 * 
 * 为什么需要这个文件？
 * - 统一管理所有服务器配置，避免配置分散
 * - 确保中间件按正确顺序加载
 * - 提供统一的错误处理和日志记录
 */

// 导入必要的依赖包 - Import necessary dependencies
import express from "express";        // Express 框架，用于创建 Web 服务器 - Express framework for creating web server
                                      // 为什么选择 Express？因为它是 Node.js 最流行的 Web 框架，提供了丰富的中间件生态
import cors from "cors";              // 跨域资源共享中间件 - Cross-Origin Resource Sharing middleware
                                      // 为什么需要 CORS？因为前端和后端通常运行在不同端口，浏览器默认阻止跨域请求
import helmet from "helmet";          // 安全中间件，设置各种 HTTP 头部 - Security middleware for setting HTTP headers
                                      // 为什么使用 helmet？它能自动设置多个安全相关的 HTTP 头部，防止 XSS、点击劫持等攻击
import morgan from "morgan";          // HTTP 请求日志中间件 - HTTP request logging middleware
                                      // 为什么需要日志？便于开发调试和生产环境监控，记录每个 API 请求的详细信息
import dotenv from "dotenv";          // 环境变量加载器 - Environment variables loader
                                      // 为什么使用环境变量？将敏感信息（如数据库密码、API密钥）与代码分离，提高安全性

// 导入自定义模块 - Import custom modules
import { initDatabase } from "./data/database.js";      // 数据库初始化函数 - Database initialization function
                                                        // 为什么单独封装？确保数据库连接在应用启动前建立，避免后续操作失败
import authRoutes from "./routes/authRoutes.js";        // 用户认证路由 - User authentication routes
                                                        // 为什么分离路由？模块化管理，每个功能模块独立维护，便于团队协作
import calendarRoutes from "./routes/calendar.js";      // 日历相关路由 - Calendar related routes
                                                        // 为什么需要日历路由？提供农历、节气、黄历等传统文化功能
import fortuneRoutes from "./routes/fortune.js";        // 运势相关路由 - Fortune related routes
                                                        // 为什么需要运势路由？这是应用的核心功能，提供算命、占卜等服务
import { errorHandler } from "./middleware/errorHandler.js"; // 错误处理中间件 - Error handling middleware
                                                            // 为什么统一错误处理？确保所有错误都有一致的响应格式，便于前端处理

/**
 * 第一步：加载环境变量配置文件 (.env)
 * 
 * 为什么这一步必须最先执行？
 * - 后续的数据库连接、端口配置等都依赖环境变量
 * - 如果环境变量加载失败，整个应用无法正常启动
 * - dotenv.config() 会读取项目根目录的 .env 文件，将其中的变量加载到 process.env 中
 */
dotenv.config();

/**
 * 第二步：创建 Express 应用实例
 * 
 * 为什么使用 Express？
 * - 轻量级且灵活的 Node.js Web 框架
 * - 丰富的中间件生态系统
 * - 简洁的 API 设计，易于学习和使用
 * - 广泛的社区支持和文档
 */
const app = express();

/**
 * 第三步：初始化数据库连接
 * 
 * 为什么在这里初始化数据库？
 * - 确保在处理任何请求之前，数据库连接已经建立
 * - 使用 await 确保数据库初始化完成后再继续执行
 * - 如果数据库连接失败，应用会在启动阶段就报错，而不是在运行时
 */
await initDatabase();

/**
 * 第四步：配置安全和功能中间件
 * 
 * 中间件的执行顺序很重要！每个请求都会按顺序经过这些中间件
 */

// helmet() - 设置安全相关的 HTTP 头部
// 为什么需要 helmet？
// - 自动设置 X-Content-Type-Options: nosniff（防止 MIME 类型嗅探攻击）
// - 设置 X-Frame-Options: DENY（防止点击劫持）
// - 设置 X-XSS-Protection: 1; mode=block（启用 XSS 过滤）
// - 移除 X-Powered-By 头部（隐藏服务器技术栈信息）
app.use(helmet());

// cors() - 允许跨域请求
// 为什么需要 CORS？
// - 前端应用（如 React）通常运行在 3000 端口
// - 后端 API 运行在 5000 端口
// - 浏览器的同源策略会阻止这种跨域请求
// - CORS 中间件告诉浏览器允许这种跨域访问
app.use(cors());

// morgan("dev") - 记录 HTTP 请求日志
// 为什么使用 "dev" 格式？
// - 在开发环境下提供彩色、简洁的日志输出
// - 包含请求方法、URL、状态码、响应时间等关键信息
// - 便于开发者快速定位问题
app.use(morgan("dev"));

// express.json() - 解析 JSON 格式的请求体
// 为什么需要这个中间件？
// - 现代 Web API 主要使用 JSON 格式传输数据
// - 没有这个中间件，req.body 将是 undefined
// - 它会自动将 JSON 字符串解析为 JavaScript 对象
app.use(express.json());

// express.urlencoded() - 解析 URL 编码的请求体（表单数据）
// 为什么需要 extended: true？
// - extended: true 使用 qs 库解析，支持嵌套对象
// - extended: false 使用 querystring 库，只支持简单键值对
// - 我们选择 true 以支持更复杂的表单数据结构
app.use(express.urlencoded({ extended: true }));

/**
 * 第五步：注册 API 路由
 * 
 * 为什么使用路由前缀？
 * - 便于 API 版本管理（如 /api/v1、/api/v2）
 * - 清晰的 URL 结构，便于前端开发者理解
 * - 便于在网关层进行路由和负载均衡
 */

// 所有认证相关的 API 都会以 /api/auth 开头
// 例如：POST /api/auth/login, POST /api/auth/register
app.use("/api/auth", authRoutes);

// 所有日历相关的 API 都会以 /api/calendar 开头
// 例如：GET /api/calendar/lunar, GET /api/calendar/solar
app.use("/api/calendar", calendarRoutes);

// 所有运势相关的 API 都会以 /api/fortune 开头
// 例如：GET /api/fortune/daily, POST /api/fortune/calculate
app.use("/api/fortune", fortuneRoutes);

/**
 * 第六步：健康检查端点
 * 
 * 为什么需要健康检查？
 * - 便于运维监控服务器状态
 * - 负载均衡器可以通过此接口判断服务是否正常
 * - 在容器化部署时，用于健康检查和自动重启
 */
app.get("/api/health", (req, res) => {
  res.json({ 
    status: "OK",                           // 服务器状态 - 告诉调用者服务正常运行
    timestamp: new Date().toISOString(),    // 当前时间戳 - 提供服务器当前时间，便于调试时区问题
    uptime: process.uptime(),               // 服务运行时间（秒）- 显示服务已运行多长时间
    memory: process.memoryUsage(),          // 内存使用情况 - 便于监控内存泄漏
    version: process.env.npm_package_version || "1.0.0"  // 应用版本 - 便于版本管理和问题追踪
  });
});

/**
 * 第七步：404 错误处理
 * 
 * 为什么需要 404 处理？
 * - 当用户访问不存在的 API 路径时，给出明确的错误信息
 * - 避免返回默认的 HTML 404 页面（对 API 来说不合适）
 * - 统一错误响应格式，便于前端处理
 */
app.use((req, res) => {
  res.status(404).json({ 
    success: false,
    message: "请求的资源不存在",
    error: "NOT_FOUND",
    path: req.originalUrl,                  // 记录用户请求的路径，便于调试
    method: req.method,                     // 记录请求方法，便于调试
    timestamp: new Date().toISOString()     // 错误发生时间
  });
});

/**
 * 第八步：全局错误处理中间件
 * 
 * 为什么需要全局错误处理？
 * - 捕获所有未被路由处理的错误
 * - 确保错误响应格式的一致性
 * - 防止服务器因未处理的错误而崩溃
 * - 记录错误日志，便于问题排查
 * 
 * 注意：这个中间件必须放在最后，因为它需要捕获前面所有中间件的错误
 */
app.use(errorHandler);

/**
 * 导出应用实例供其他模块使用
 * 
 * 为什么使用 export default？
 * - 这个文件的主要目的就是导出配置好的 Express 应用
 * - 使用默认导出让其他文件导入时更简洁
 * - server.js 文件会导入这个应用实例并启动服务器
 */
export default app;
// ============后端应用主文件结束===========
